[iOS 8] CMPedometer で歩数を取得する
歩数計機能
iOS 8 の Core Motion フレームワークに CMPedometer という歩数関連のデータを取得することができる API が追加されました。このクラスを使うと歩数/走行距離/昇り降りしたフロアの数などを計測できたり、過去に遡ってデータを参照できたりします。
なお、iOS 7 で追加された CMStepCounter がありますが、これの機能増強版と言えます。CMStepCounter は Deprecated になりました。短命でしたね。。
NS_CLASS_DEPRECATED_IOS(7_0,8_0,"Use CMPedometer instead") @interface CMStepCounter : NSObject
この API は iPhone 5s に搭載されているモーション・コプロセッサー「M7」以降を利用して歩数を計測するので、電池消費量がかなり少ないです。
CMPedometer を使ってみよう
ということで早速使ってみましょう。まずプロジェクトを作成し Core Motion フレームワークを追加します。
モニタリング
あとはもう実装だけです。まずはモニタリングを行ってみましょう。
// メンバー変数でないと動作しないので注意 let pedometer = CMPedometer() func startStepCounting() { // CMPedometerが利用できるか確認 if CMPedometer.isStepCountingAvailable() { // 計測開始 pedometer.startPedometerUpdatesFromDate(NSDate(), withHandler: { [unowned self] data, error in dispatch_async(dispatch_get_main_queue(), { println("update") if error != nil { // エラー self.label.text = "エラー : \(error)" println("エラー : \(error)") } else { let lengthFormatter = NSLengthFormatter() // 歩数 let steps = data.numberOfSteps // 距離 let distance = data.distance.doubleValue // 速さ let time = data.endDate.timeIntervalSinceDate(data.startDate) let speed = distance / time // 上った回数 let floorsAscended = data.floorsAscended // 降りた回数 let floorsDescended = data.floorsDescended // 結果をラベルに出力 self.label.text = "Steps: \(steps)" + "\n\nDistance : \(lengthFormatter.stringFromMeters(distance))" + "\n\nSpeed : \(lengthFormatter.stringFromMeters(speed)) / s" + "\n\nfloorsAscended : \(floorsAscended)" + "\n\nfloorsDescended : \(floorsDescended)" } }) }) } }
まずはじめに CMPedometer#isStepCountingAvailable を呼びます。歩数測定ができるデバイス (= M7) のときに true が返ります。測定可能な場合のみ処理を行うようにしましょう。
次に CMPedometer インスタンスを生成し、CMPedometer#startPedometerUpdatesFromDate:withHandler を呼びます。
第一引数は、今までのデータを取得できるように NSDate が指定できるようになっています。メソッドのコール時から計測したい場合は NSDate を生成して渡します。第二引数にはハンドラを渡します。データは CMPedometerData オブジェクトとして渡されます。新しいデータが追加されると、ハンドラがバックグラウンドで繰り返し呼び出されます。別スレッドで呼ばれるので、この中で View の更新などを行いたい場合はメインスレッドで処理しましょう。
実行します。Core Motion フレームワークの API を利用するにはユーザーのプライバシー許可が必要になるため、初回実行時は次のようなダイアログが表示されます。
許可すると、歩数や距離、速さが取得できます。
データの参照
次に過去のデータを参照してみましょう。
func showHistory() { // CMPedometerが利用できるか確認 if CMPedometer.isStepCountingAvailable() { // この日から let fromDate = NSDate(timeIntervalSinceNow: -60 * 60 * 24 * 7) // この日まで let toDate = NSDate() pedometer.queryPedometerDataFromDate(fromDate, toDate: toDate, withHandler: { [unowned self] data, error in dispatch_async(dispatch_get_main_queue(), { println("update") if error != nil { // エラー self.label.text = "エラー : \(error)" println("エラー : \(error)") } else { let lengthFormatter = NSLengthFormatter() // 歩数 let steps = data.numberOfSteps // 距離 let distance = data.distance.doubleValue // 速さ let time = data.endDate.timeIntervalSinceDate(data.startDate) let speed = distance / time // 上った回数 let floorsAscended = data.floorsAscended // 降りた回数 let floorsDescended = data.floorsDescended // 結果をラベルに出力 self.label.text = "Steps: \(steps)" + "\n\nDistance : \(lengthFormatter.stringFromMeters(distance))" + "\n\nSpeed : \(lengthFormatter.stringFromMeters(speed)) / s" + "\n\nfloorsAscended : \(floorsAscended)" + "\n\nfloorsDescended : \(floorsDescended)" } }) }) } }
過去のデータを取得するには CMPedometer#queryPedometerDataFromDate:toDate:withHandler を呼びます。第一引数、第二引数には取得したい期間を指定し、第三引数には取得結果のコールバックのハンドラを渡します。取得できた場合、モニタリング時と同様 CMPedometerData オブジェクトとして取得できます。
実行すると次のように、期間内の歩数や距離などが取得できます。
まとめ
歩数計機能は CMStepCounter から更に機能が上がっています。歩数などの健康に関する情報は HealthKit でも扱えるようになったので、ユーザーにより身近な存在になったと言えるでしょう。ぜひアプリで活用したいですね。